import pygame

import basemaze

pygame.init()

SMILE = pygame.image.load('smile.png')

PIECESIZE = 20
HALFPIECE = PIECESIZE / 2

FONT = pygame.font.Font(None , 20)

BLACK = [0, 0, 0]
RED = [255, 0, 0]
GREEN = [0, 255, 0]

class Smiley:
    def __init__(self, maze):
        self.maze = maze
        self.maze_position = [self.maze.start.x, self.maze.start.y]
        self.screen_position = [0, 0]
        self.direction = [0, 0]
        self.do_move()
        self.passed_fields = [[self.maze.start.x * PIECESIZE + 10,
                                self.maze.start.y * PIECESIZE + 10]]
    
    def do_move(self):
        if self.direction[0] or self.direction[1]:
            self.maze_position[0] += self.direction[0]
            self.maze_position[1] += self.direction[1]
            self.passed_fields.append([self.maze_position[0] * PIECESIZE + HALFPIECE,
                                       self.maze_position[1] * PIECESIZE + HALFPIECE])
            self.direction = [0, 0]
        self.screen_position[0] = self.maze_position[0] * PIECESIZE + 2
        self.screen_position[1] = self.maze_position[1] * PIECESIZE + 2
    
    def flip(self):
        self.maze.screen.blit(self.maze.mscreen, (0, 0))
        if len(self.passed_fields) > 1 and self.maze.line:
            pygame.draw.lines(self.maze.screen, pygame.color.Color(0, 0, 255), False, self.passed_fields, 1)
        self.maze.screen.blit(SMILE, self.screen_position)
        self.maze.screen.blit(FONT.render("Passed Fields: " + str(len(self.passed_fields)-1), False, [0, 0, 0]),
                              [5, self.maze.height * PIECESIZE + 5])
        self.maze.screen.blit(FONT.render("Shortest Way: " + str(self.maze.waylength), False, [0, 0, 0]),
                              [5, self.maze.height * PIECESIZE + 25])
        pygame.display.flip() 
    
    def tick(self):
        self.screen_position[0] += self.direction[0]
        self.screen_position[1] += self.direction[1]
        self.flip()
    
    def change_direction(self, new_direction):
        if self.maze.get_field(*self.maze_position).type == basemaze.AIM:
            pass
        else:
            aim = self.maze.get_field(self.maze_position[0] + new_direction[0],
                                      self.maze_position[1] + new_direction[1])
            if aim:
                if aim.type != basemaze.WALL:
                    self.direction = new_direction

class GraphicField(basemaze.Basefield):
    def __init__(self, maze, x, y):
        basemaze.Basefield.__init__(self, maze, x, y)
    
    def center(self):
        return [int(self.x * PIECESIZE + HALFPIECE), int(self.y * PIECESIZE + HALFPIECE)]
        

class GraphicMaze(basemaze.Maze):
    def __init__(self, caption, width, height, design, line, algorithm, start):
        basemaze.Maze.__init__(self, width, height, GraphicField)
        self.width = width
        self.height = height
        self.screen = pygame.display.set_mode((width * PIECESIZE, height * PIECESIZE + 40))
        pygame.display.set_caption(caption)
        self.mscreen = pygame.surface.Surface((width * PIECESIZE, height * PIECESIZE + 40))
        self.mscreen.fill([255, 255, 255])
        exec('self.' + algorithm + '(' + start + ')')
        longestwayfield = basemaze.Basefield(None, None, None)
        for i in range(self.width):
            for j in range(self.height):
                if self.fields[i][j].waylength > longestwayfield.waylength:
                    longestwayfield = self.fields[i][j]
        longestwayfield.type = basemaze.AIM
        self.waylength = longestwayfield.waylength
        if design == 1:
            self.draw_maze_line()
        else:
            self.draw_maze_block()
        pygame.draw.line(self.mscreen, [0,0,0], [0, height * PIECESIZE + 2], [width * PIECESIZE , height * PIECESIZE + 2], 4)
        self.line = line
    
    def draw_maze_block(self):
        for i in enumerate(self.fields):
            for j in enumerate(i[1]):
                if j[1].type == basemaze.WALL:
                    pygame.draw.rect(self.mscreen, [200, 200, 200], [i[0] * PIECESIZE, j[0] * PIECESIZE, PIECESIZE, PIECESIZE])
                elif j[1].type == basemaze.AIM:
                    pygame.draw.rect(self.mscreen, [255, 0, 0], [i[0] * PIECESIZE, j[0] * PIECESIZE, PIECESIZE, PIECESIZE])
                elif j[1].type == basemaze.START:
                    pygame.draw.rect(self.mscreen, [0, 255, 0], [i[0] * PIECESIZE, j[0] * PIECESIZE, PIECESIZE, PIECESIZE])
    
    def draw_line(self, start, x, y):
        aim =  self.get_field(start.x + x, start.y - y)
        if aim: 
            if aim.type == basemaze.WALL:
                pygame.draw.line(self.mscreen, BLACK, start.center(), aim.center(), 1)
    
    def draw_maze_line(self):
        for i in enumerate(self.fields):
            for j in enumerate(i[1]):
                if j[1].type == basemaze.WALL:
                    pygame.draw.circle(self.mscreen, BLACK, j[1].center(), 5)
                    self.draw_line(j[1], 1, 0)
                    self.draw_line(j[1], 0, 1)
                    if self.diagonal_walls:
                        self.draw_line(j[1], 1, 1)
                        self.draw_line(j[1], -1, 1)
                elif j[1].type == basemaze.START:
                    pygame.draw.circle(self.mscreen, RED, j[1].center(), 10)
                elif j[1].type == basemaze.AIM:
                    pygame.draw.circle(self.mscreen, GREEN, j[1].center(), 10)
                    
    def mainloop(self):
        pygame.time.set_timer(pygame.USEREVENT, 100)
        pygame.time.set_timer(pygame.USEREVENT + 1, 25)
        smiley = Smiley(self)
        while True:
            for event in pygame.event.get():
                if event.type == pygame.USEREVENT: # + 1:
                    smiley.tick()
                if event.type == pygame.QUIT:
                    pygame.display.quit()
                    return
                elif event.type == pygame.USEREVENT:
                    smiley.do_move()
                    if pygame.key.get_pressed()[pygame.K_DOWN]:
                        smiley.change_direction([0, 1])
                    elif pygame.key.get_pressed()[pygame.K_UP]:
                        smiley.change_direction([0, -1])
                    elif pygame.key.get_pressed()[pygame.K_RIGHT]:
                        smiley.change_direction([1, 0])
                    elif pygame.key.get_pressed()[pygame.K_LEFT]:
                        smiley.change_direction([-1, 0])